package org.news.web.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.redis.utils.RedisUtils;
import org.news.web.domain.Likes;
import org.news.web.domain.News;
import org.news.web.domain.Users;
import org.news.web.mapper.NewsMapper;
import org.news.web.mapper.UsersMapper;
import org.news.web.redis.RedisConstant;
import org.springframework.stereotype.Service;
import org.news.web.domain.bo.FavoritesBo;
import org.news.web.domain.vo.FavoritesVo;
import org.news.web.domain.Favorites;
import org.news.web.mapper.FavoritesMapper;
import org.news.web.service.IFavoritesService;

import java.util.HashSet;
import java.util.List;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 收藏功能Service业务层处理
 *
 * @author Gu Ci
 * @date 2024-04-03
 */
@RequiredArgsConstructor
@Service
public class FavoritesServiceImpl implements IFavoritesService {

    private final FavoritesMapper baseMapper;

    private final UsersMapper usersMapper;


    private final NewsMapper newsMapper;

    /**
     * 查询收藏功能
     */
    @Override
    public FavoritesVo queryById(Long favoriteId){
        return baseMapper.selectVoById(favoriteId);
    }

    /**
     * 查询收藏功能列表
     */
    @Override
    public TableDataInfo<FavoritesVo> queryPageList(FavoritesBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<Favorites> lqw = buildQueryWrapper(bo);
        Page<FavoritesVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);


        /**
         * 获取用户和新闻
         */
        if(ObjectUtil.isNotNull(result.getRecords()) && result.getRecords().size() >0){
            Set<Long> collect = result.getRecords().stream().map(item -> {
                return item.getUserId();
            }).collect(Collectors.toSet());

            List<Users> users = usersMapper.selectList(new LambdaQueryWrapper<Users>().in(Users::getUserId, collect));
            users.forEach(user ->{
                result.getRecords().stream().forEach(item ->{
                    if(item.getUserId() == user.getUserId()){
                        item.setUsername(user.getUsername());
                    }
                });
            });
        }
        /**
         * 获取新闻标题
         */
        if(ObjectUtil.isNotNull(result.getRecords()) && result.getRecords().size() >0){
            Set<Long> collect = result.getRecords().stream().map(item -> {
                return item.getNewsId();
            }).collect(Collectors.toSet());
            List<News> news = newsMapper.selectList(new LambdaQueryWrapper<News>().in(News::getNewsId, collect));

            news.stream().forEach(New->{
                result.getRecords().forEach(item ->{
                    if(New.getNewsId() == item.getNewsId()){
                        item.setTitle(New.getTitle());
                    }
                });
            });
        }

        return TableDataInfo.build(result);
    }

    /**
     * 查询收藏功能列表
     */
    @Override
    public List<FavoritesVo> queryList(FavoritesBo bo) {
        LambdaQueryWrapper<Favorites> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<Favorites> buildQueryWrapper(FavoritesBo bo) {
        LambdaQueryWrapper<Favorites> lqw = Wrappers.lambdaQuery();
        Set<Long> userIds = null;
        if(bo.getUserId() == null){
            if(StringUtils.isNotBlank(bo.getUsername())){
                List<Users> username = usersMapper.selectList(new QueryWrapper<Users>().like("username", bo.getUsername()));
                if(ObjectUtil.isNotNull(username) && username.size() >0){
                    userIds = username.stream().map(Users::getUserId).collect(Collectors.toSet());
                }else{
//                查询不到用户 给一个查不到的id
                    userIds = new HashSet<>();
                    userIds.add(-1l);
                }
            }
            lqw.in(userIds!= null, Favorites::getUserId, userIds);
        }else{
            lqw.eq(userIds!= null, Favorites::getUserId, bo.getUserId());
        }
        return lqw;
    }

    /**
     * 新增收藏功能
     */
    @Override
    public Boolean insertByBo(FavoritesBo bo) {
        Favorites add = MapstructUtils.convert(bo, Favorites.class);
        validEntityBeforeSave(add);
        boolean flag = favo(add.getUserId(),add.getNewsId())>0;
        return flag;
    }

    /**
     * 修改收藏功能
     */
    @Override
    public Boolean updateByBo(FavoritesBo bo) {
        Favorites update = MapstructUtils.convert(bo, Favorites.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Favorites entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除收藏功能
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        String key = RedisConstant.NEWS_PRE_KEY +":"+RedisConstant.FAVO_PRE_KEY+":";
//        删除缓存
        ids.forEach(
            item->{
                Favorites favorites = baseMapper.selectById(item);
                //删除缓存
                RedisUtils.delSetOne(key+favorites.getNewsId(),favorites.getUserId());
//                删除行为数据
                RedisUtils.setCacheMapValue(RedisConstant.XIN_WEI + ":" + favorites.getUserId() + ":" + favorites.getNewsId(),RedisConstant.IS_FAVO,0);
            }
        );
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public int favo(Long userId, Long newsId) {
        String key = RedisConstant.NEWS_PRE_KEY +":"+RedisConstant.FAVO_PRE_KEY+":"+newsId;
        // 同步缓存进行处理  用于后台
        // 1.查询缓存是否该用户已经点收藏
        if (isFavo(userId,newsId)) {
//            点收藏就不需要重新点了
            throw new ServiceException("该用户已经收藏过了 无法在收藏");
        }
        //2.添加缓存信息
        boolean b = RedisUtils.addCacheSet(key, userId);
        System.out.println("缓存信息添加："+b);
        //        3.添加行为数据缓存
        String XINWEN_KEY = RedisConstant.XIN_WEI + ":" + userId + ":" + newsId;
        RedisUtils.setCacheMapValue(XINWEN_KEY,RedisConstant.IS_FAVO,1);
        //3.数据库中进行添加
        Favorites favorites = new Favorites();
        favorites.setUserId(userId);
        favorites.setNewsId(newsId);
        baseMapper.insert(favorites);
        return 1;
    }

    @Override
    public int nofavo(Long userId, Long newsId) {
        String key = RedisConstant.NEWS_PRE_KEY +":"+RedisConstant.FAVO_PRE_KEY+":"+newsId;
        // 同步缓存进行处理 用于后台
//        1.查询缓存是否该用户已经点过赞点赞
        if (!isFavo(userId,newsId)) {
            throw new ServiceException("该用户没有收藏 无法删除");
        }
//        2.进行取消点赞操作
//        删除redis中的用户信息
        boolean b = RedisUtils.delSetOne(key, userId);
        System.out.println("缓存信息删除："+b);
//        3.添加行为数据缓存
        String XINWEN_KEY = RedisConstant.XIN_WEI + ":" + userId + ":" + newsId;
        RedisUtils.setCacheMapValue(XINWEN_KEY,RedisConstant.IS_FAVO,0);
//        删除数据库数据保存同步
        baseMapper.delete(new LambdaQueryWrapper<Favorites>().eq(Favorites::getUserId,userId).eq(Favorites::getNewsId,newsId));
        return 1;
    }

    public boolean isFavo(Long userId,Long newsId){
        String key = RedisConstant.NEWS_PRE_KEY +":"+RedisConstant.FAVO_PRE_KEY+":"+newsId;
        return RedisUtils.isContains(key,userId);
    }
}
